#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
                            _ooOoo_  
                           o8888888o  
                           88" . "88  
                          (|  -_-  |)  
                           O\  =  /O  
                        ____/`---'\____  
                      .   ' \\| |// `.  
                       / \\||| : |||// \  
                     / _||||| -:- |||||- \  
                       | | \\\ - /// | |  
                     | \_| ''\---/'' | |  
                      \ .-\__ `-` ___/-. /  
                   ___`. .' /--.--\ `. . __  
                ."" '< `.___\_<|>_/___.' >'"".  
               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
                 \ \ `-. \_ __\ /__ _/ .-` / /  
         ======`-.____`-.___\_____/___.-`____.-'======  
                            `=---='  
  
         .............................................  
                  佛祖镇楼                  BUG辟易  
          佛曰:  
                  写字楼里写字间，写字间里程序员；  
                  程序人员写程序，又拿程序换酒钱。  
                  酒醒只在网上坐，酒醉还来网下眠；  
                  酒醉酒醒日复日，网上网下年复年。  
                  但愿老死电脑间，不愿鞠躬老板前；  
                  奔驰宝马贵者趣，公交自行程序员。  
                  别人笑我忒疯癫，我笑自己命太贱；  
                  不见满街漂亮妹，哪个归得程序员？ 
'''
# @File  : modbus_slave_1.py
# @Author: huguangzhi
# @Drivce: Thinkpad E470
# @ContactEmail : huguangzhi@ucsdigital.com.com 
# @ContactPhone : 13121961510 
# @Date  : 2021/7/16 - 17:14
# @Desc  :


import sys

import modbus_tk
import modbus_tk.defines as cst
from modbus_tk import modbus_tcp


def main():
    """main"""

    logger = modbus_tk.utils.create_logger(name="console", record_format="%(message)s")

    try:
        # Create the server
        #  创建一个TCPserver，这里可以指定设置端口号，地址，超时时间 当然这是slave不需要
        # server = modbus_tcp.TcpServer()
        server = modbus_tcp.TcpServer(port=60001, address='127.0.0.1')
        logger.info("running...")
        logger.info("enter 'quit' for closing the server")

        server.start()
        # TCP server添加一个slave
        slave_1 = server.add_slave(1)
        # 添加块地址，对应的分别为块名字，快类型，块开始地址，块的容量大小
        slave_1.add_block('0', cst.HOLDING_REGISTERS, 0, 100)

        # 开始数据输入
        while True:
            # 从标准输入开始接收拿到数据，按照空格分隔
            cmd = sys.stdin.readline()
            args = cmd.split(' ')

            # 如果发现拿到的数据内容有quit字符，则退出TVP server
            if cmd.find('quit') == 0:
                sys.stdout.write('bye-bye\r\n')
                break

            # 如果有add_slave作为第一个字符，则进行添加
            # add_slave 1
            elif args[0] == 'add_slave':
                # 设置slaveID
                slave_id = int(args[1])
                server.add_slave(slave_id)
                # 输入告诉已经添加了slave信息
                sys.stdout.write('done: slave %d added\r\n' % slave_id)

            # 如果有add_block 为第一个字符，则进行添加块信息，相当于给slave设置块信息
            # 块信息不能有重叠，每种类型只能有一个块对应于给定的地址
            # 也就是说一个地址不能有两个寄存器的块信息
            # 需要输入slaveID之后，设置当前块的名字，设置块的类型，开始的address
            # add_block 1 0 0 10 10
            elif args[0] == 'add_block':
                slave_id = int(args[1])  # 需要输入slaveID
                name = args[2] # 设置当前块的名字 名字唯一不能重复
                block_type = int(args[3]) # 设置块的类型
                starting_address = int(args[4]) # 开始的数据address,从零开始的正整数
                length = int(args[5]) # 单个块的大小，参数中的size 必须是正整数
                slave = server.get_slave(slave_id)
                slave.add_block(name, block_type, starting_address, length)
                sys.stdout.write('done: block %s added\r\n' % name)

            # 设置slave的值
            # 例如：set_values 1 0 1 2 3 6 12解释
            # 第一个参数1是从站的号，第二个参数0是从站的块序号，第三个参数1是开始的地址，
            # 后面的参数2 3 6 12是从地址1开始写，有几个参数写几个地址，依次后排
            elif args[0] == 'set_values':
                slave_id = int(args[1])
                name = args[2]
                address = int(args[3])
                values = []
                for val in args[4:]:
                    values.append(int(val))
                slave = server.get_slave(slave_id)
                # 主要是这里设置slave的值 其中value 是一个数组的形式
                slave.set_values(name, address, values)
                values = slave.get_values(name, address, len(values))
                # 输出返回了写入的信息
                sys.stdout.write('done: values written: %s\r\n' % str(values))


            # 获取的slave上的信息
            elif args[0] == 'get_values':
                slave_id = int(args[1])
                name = args[2]
                address = int(args[3])
                length = int(args[4])
                slave = server.get_slave(slave_id)
                values = slave.get_values(name, address, length)
                sys.stdout.write('done: values read: %s\r\n' % str(values))

            else:
                sys.stdout.write("unknown command %s\r\n" % args[0])
    finally:
        server.stop()


if __name__ == "__main__":
    main()
    '''
    1.set_values 1 0 1 2 3 6 12解释

    第一个参数1是从站的号，第二个参数0是从站的块序号，第三个参数1是开始的地址，

    后面的参数2 3 6 12是从地址1开始写，有几个参数写几个地址，依次后排

    2.get_values 1 0 1 4解释：

    第一个参数1是从站的号，第二个参数0是从站的块序号，第三个参数1是开始的地址，

    后面的参数4是从开始地址往后数4个进行读取。

    可以连接一个实际的从站，也可以连接一个调试助手的从站，运行结果如下：

                '''